home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_09_09
/
9n09053a
< prev
next >
Wrap
Text File
|
1990-01-14
|
5KB
|
131 lines
Listing 4. Datagram sockets example. Client Program.
/* getservice -- a datagram transmission example. client program. Works with
* the server program 'services'. The program asks the server 'services', which
* is running on the same machine or in a remote host, for the presence of a
* specified service on the server machine. The server looks up the "/etc/services"
* file and sends an answer to the client. If the service exists, the answer gives
* its name, the port number and the protocol used.
*
* Usage: getservice <server host name>
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <signal.h>
#include <sys/errno.h>
#define FAIL 1
#define SUCC 0
#define PORT_NUMBER 2228 /* arbitrarily chosen free port number
* for client-server communication. Must
* be the same in both client and server
*/
#define MAXTRIES 3 /* maximum number of retransmissions before giving up */
#define PROMPT printf("Service Sought (ctrl-d to exit) : ")
/* ------------------------------------------------------------------- */
main(ac, av)
int ac; char **av ;
{
int sock ; /* socket descriptor */
struct sockaddr_in sock_addr ; /* local socket address structure */
char *progr_name = av[0] ; /* the present program name */
char *server_name = av[1] ; /* server name given on command line */
char service_name[30] ; /* service name to be asked for */
char return_message[256] ; /* buffer for response from the server */
struct hostent *host_struct, *gethostbyname() ;
void error() ; /* the same as in listing 1 */
int num_tries ; /* the current number of transmission retries */
int alarm_handler() ; /* the new alarm signal handler routine */
extern int errno ; /* system call error number */
if (ac != 2) {
fprintf(stderr, "error -- usage: %s <server name>\n", progr_name) ;
exit(FAIL) ;
}
/* get server address */
if ((host_struct = gethostbyname(server_name)) == NULL) {
fprintf(stderr, "%s: unknown server %s\n", progr_name, server_name) ;
exit(FAIL) ;
}
/* allocate a datagram socket descriptor */
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
error(progr_name, ": error opening socket") ;
/* copy server address and type to socket structure */
bcopy(host_struct->h_addr, (char *)&sock_addr.sin_addr.s_addr,
host_struct->h_length) ;
sock_addr.sin_port = PORT_NUMBER ;
sock_addr.sin_family = AF_INET ;
/* redirect alarm signal to new signal handler */
(void)signal(SIGALRM, alarm_handler) ;
/* send messages to remote host */
while (PROMPT, gets(service_name) != NULL) {
num_tries = 0 ;
for ( ; ; ) {
int nread ;
if (sendto(sock, service_name, sizeof service_name, 0,
(struct sockaddr *)&sock_addr, sizeof sock_addr ) == -1)
error(progr_name, ": error sending datagram to remote host") ;
/* the "recv" blocks until an answer from the server arrives. Since we
* are in a connectionless environment, reliable transmission isn't
* guaranteed. For this reason, and although lost packets are very
* unlikely, we set up a timeout with the call to alarm. If the timeout
* expires, we retransmit the nessage a maximum of MAX_TRIES times.
* We also assume that messages can come only from the 'service' server,
* otherwise "recvfrom should be used.
*/
(void)alarm(5) ;
if ((nread = recv(sock, return_message, sizeof return_message, 0)) <= 0) {
if (nread < 0 && errno != EINTR)
error(progr_name, ": receive failed") ;
if (num_tries++ < MAXTRIES)
continue ;
else {
fprintf(stderr, "timeout: no response from %s\n",
server_name) ;
exit(FAIL) ;
}
}
else /* got an answer from the server */
break ;
}
(void)alarm(0) ; /* turn off alarm clock */
/* print out the server response */
printf("%s\n", return_message) ;
}
putchar('\n') ;
if (close(sock) == -1)
error(progr_name, ": error closing socket") ;
exit(SUCC) ;
}
/* --------------------------------------------------------------------- */
/* alarm_handler -- new handler for the alarm signal. The default action
* associated with a signal is reset once caugth, so it must be reset
* to the intended action each time.
*/
int alarm_handler()
{
(void)signal(SIGALRM, alarm_handler) ;
}
/* --------------------------------------------------------------------- */